﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using System.Windows.Forms;
using System.Collections;
using System.Drawing.Printing;

namespace HomeCare.View
{
    public class PrintDGV
    {
        private static StringFormat StrFormat;
        private static StringFormat StrFormatComboBox;
        private static Button CellButton;
        private static CheckBox CellCheckBox;
        private static ComboBox CellComboBox;

        private static int TotalWidth;
        private static int RowPos;
        private static bool NewPage;
        private static int PageNo;
        private static ArrayList ColumnLefts = new ArrayList();
        private static ArrayList ColumnWidths = new ArrayList();
        private static ArrayList ColumnTypes = new ArrayList();
        private static int CellHeight;
        private static int RowsPerPage;
        private static PrintDocument printDoc = new PrintDocument();
        private static string PrintTitle = "";
        private static DataGridView dgv;
        private static List<string> SelectedColumns = new List<string>();
        private static List<string> AvailableColumns = new List<string>();
        private static bool PrintAllRows = true;
        private static bool FitToPageWidth = true;
        private static int HeaderHeight = 0;

        public static void Print_DataGridView(DataGridView dgv1, String titulo)
        {
            PrintPreviewDialog ppvw;
            try
            {
                dgv = dgv1;
                AvailableColumns.Clear();

                foreach (DataGridViewColumn c in dgv.Columns)
                {
                    if (!c.Visible) continue;
                    AvailableColumns.Add(c.HeaderText);
                }

                PrintOptions dlg = new PrintOptions(AvailableColumns, titulo);
                if (dlg.ShowDialog() != DialogResult.OK)
                    return;
                PrintTitle = dlg.PrintTitle;
                SelectedColumns = dlg.GetSelectedColumns();
                RowsPerPage = 0;

                ppvw = new PrintPreviewDialog();
                ppvw.Document = printDoc;
                printDoc.BeginPrint += new PrintEventHandler(printDoc_BeginPrint);
                printDoc.PrintPage += new PrintPageEventHandler(printDoc_PrintPage);

                if (ppvw.ShowDialog() != DialogResult.OK)
                {
                    printDoc.BeginPrint -= new PrintEventHandler(printDoc_BeginPrint);
                    printDoc.PrintPage -= new PrintPageEventHandler(printDoc_PrintPage);
                    return;
                }

                printDoc.Print();
                printDoc.BeginPrint -= new PrintEventHandler(printDoc_BeginPrint);
                printDoc.PrintPage -= new PrintPageEventHandler(printDoc_PrintPage);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, "Erro", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
            finally
            {
            }
        }

        private static void printDoc_PrintPage(object sender, PrintPageEventArgs e)
        {
            int tmpWidth, i;
            int tmpTop = e.MarginBounds.Top;
            int tmpLeft = e.MarginBounds.Left;

            try
            {
                if (PageNo == 1)
                {
                    foreach (DataGridViewColumn GridCol in dgv.Columns)
                    {
                        if (!GridCol.Visible) continue;

                        if (!PrintDGV.SelectedColumns.Contains(GridCol.HeaderText)) continue;

                        if (FitToPageWidth)
                        {
                            tmpWidth = (int)(Math.Floor((double)((double)GridCol.Width /
                                      (double)TotalWidth * (double)TotalWidth *
                                      ((double)e.MarginBounds.Width / (double)TotalWidth))));
                        }
                        else
                            tmpWidth = GridCol.Width;

                        HeaderHeight = (int)(e.Graphics.MeasureString(GridCol.HeaderText, GridCol.InheritedStyle.Font, tmpWidth).Height) + 11;
                        ColumnLefts.Add(tmpLeft);
                        ColumnWidths.Add(tmpWidth);
                        ColumnTypes.Add(GridCol.GetType());
                        tmpLeft += tmpWidth;

                        HeaderHeight = (int)(e.Graphics.MeasureString(GridCol.HeaderText,
                           GridCol.InheritedStyle.Font, tmpWidth).Height) * 2;

                        ColumnLefts.Add(tmpLeft);
                        ColumnWidths.Add(tmpWidth);
                        ColumnTypes.Add(GridCol.GetType());
                        tmpLeft += tmpWidth;
                    }
                }

                while (RowPos <= dgv.Rows.Count - 1)
                {
                    DataGridViewRow GridRow = dgv.Rows[RowPos];
                    if (GridRow.IsNewRow || (!PrintAllRows && !GridRow.Selected))
                    {
                        RowPos++;
                        continue;
                    }

                    CellHeight = GridRow.Height;

                    if (tmpTop + CellHeight >= e.MarginBounds.Height + e.MarginBounds.Top)
                    {
                        DrawFooter(e, RowsPerPage);
                        NewPage = true;
                        PageNo++;
                        e.HasMorePages = true;
                        return;
                    }
                    else
                    {
                        if (NewPage)
                        {
                            e.Graphics.DrawString(PrintTitle, new Font(dgv.Font, FontStyle.Bold),
                                Brushes.Black, e.MarginBounds.Left, e.MarginBounds.Top -
                            e.Graphics.MeasureString(PrintTitle, new Font(dgv.Font, FontStyle.Bold), e.MarginBounds.Width).Height - 13);

                            String s = DateTime.Now.ToLongDateString() + " " + DateTime.Now.ToShortTimeString();

                            e.Graphics.DrawString(s, new Font(dgv.Font, FontStyle.Bold),
                                    Brushes.Black, e.MarginBounds.Left + (e.MarginBounds.Width -
                                    e.Graphics.MeasureString(s, new Font(dgv.Font,
                                    FontStyle.Bold), e.MarginBounds.Width).Width), e.MarginBounds.Top -
                                    e.Graphics.MeasureString(PrintTitle, new Font(new Font(dgv.Font,
                                    FontStyle.Bold), FontStyle.Bold), e.MarginBounds.Width).Height - 13);

                            tmpTop = e.MarginBounds.Top;
                            i = 0;

                            foreach (DataGridViewColumn GridCol in dgv.Columns)
                            {
                        		if (!GridCol.Visible) continue;
                                if (!PrintDGV.SelectedColumns.Contains(GridCol.HeaderText)) continue;

                                e.Graphics.FillRectangle(new SolidBrush(Color.LightGray),
                                    new Rectangle((int) ColumnLefts[i], tmpTop,
                                    (int) ColumnWidths[i], HeaderHeight));

                                e.Graphics.DrawRectangle(Pens.Black,
                                    new Rectangle((int) ColumnLefts[i], tmpTop,
                                        (int) ColumnWidths[i], HeaderHeight));

                                e.Graphics.DrawString(GridCol.HeaderText, GridCol.InheritedStyle.Font,
                                    new SolidBrush(GridCol.InheritedStyle.ForeColor),
                                    new RectangleF((int) ColumnLefts[i], tmpTop,
                                        (int) ColumnWidths[i], HeaderHeight), StrFormat);
                                i++;
                            }

                            NewPage = false;
                            tmpTop += HeaderHeight;
                        }

                        i = 0;

                        foreach (DataGridViewCell Cel in GridRow.Cells)
	                    {
                	        if(!Cel.OwningColumn.Visible) continue;
                            if(!SelectedColumns.Contains(Cel.OwningColumn.HeaderText))
                                continue;

                            if (((Type) ColumnTypes[i]).Name == "DataGridViewTextBoxColumn" ||
                                ((Type) ColumnTypes[i]).Name == "DataGridViewLinkColumn")
                            {
                                e.Graphics.DrawString(Cel.Value.ToString(), Cel.InheritedStyle.Font,
                                    new SolidBrush(Cel.InheritedStyle.ForeColor),
                                    new RectangleF((int) ColumnLefts[i], (float) tmpTop,
                                        (int) ColumnWidths[i], (float) CellHeight), StrFormat);
                            }
                            else if (((Type) ColumnTypes[i]).Name == "DataGridViewButtonColumn")
                            {
                                CellButton.Text = Cel.Value.ToString();
                                CellButton.Size = new Size((int) ColumnWidths[i], CellHeight);
                                Bitmap bmp = new Bitmap(CellButton.Width, CellButton.Height);
                                CellButton.DrawToBitmap(bmp, new Rectangle(0,0,
                                    bmp.Width, bmp.Height));
                                e.Graphics.DrawImage(bmp, new Point((int) ColumnLefts[i], tmpTop));
                            }
                            else if (((Type) ColumnTypes[i]).Name == "DataGridViewCheckBoxColumn")
                            {
                                CellCheckBox.Size = new Size(14,14);
                                CellCheckBox.Checked = (bool) Cel.Value;
                                Bitmap bmp = new Bitmap((int) ColumnWidths[i], CellHeight);
                                Graphics tmpGraphics = Graphics.FromImage(bmp);
                                tmpGraphics.FillRectangle(Brushes.White, new Rectangle(0,0,
                                    bmp.Width, bmp.Height));
                                CellCheckBox.DrawToBitmap(bmp,
                                    new Rectangle((int) ((bmp.Width - CellCheckBox.Width) / 2),
                                        (int) ((bmp.Height - CellCheckBox.Height) / 2),
                                        CellCheckBox.Width, CellCheckBox.Height));
                                e.Graphics.DrawImage(bmp, new Point((int) ColumnLefts[i], tmpTop));
                            }
                            else if (((Type) ColumnTypes[i]).Name == "DataGridViewComboBoxColumn")
                            {
                                CellComboBox.Size = new Size((int) ColumnWidths[i], CellHeight);
                                Bitmap bmp = new Bitmap(CellComboBox.Width, CellComboBox.Height);
                                CellComboBox.DrawToBitmap(bmp, new Rectangle(0,0,bmp.Width, bmp.Height));
                                e.Graphics.DrawString(Cel.Value.ToString(), Cel.InheritedStyle.Font,
                                    new SolidBrush(Cel.InheritedStyle.ForeColor),
                                    new RectangleF((int) ColumnLefts[i] + 1, tmpTop, (int) ColumnWidths[i] -16,
                                        CellHeight), StrFormatComboBox);
                            }

                            e.Graphics.DrawRectangle(Pens.Black, new Rectangle((int) ColumnLefts[i],
                                tmpTop, (int) ColumnWidths[i], CellHeight));
                            i++;
	                    }

                        tmpTop += CellHeight;
                    }

                    RowPos++;

                    if(PageNo == 1) RowsPerPage++;
                }

                if (RowsPerPage == 0) return;

                DrawFooter(e, RowsPerPage);

                e.HasMorePages = false;
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message,"Erro", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        private static void printDoc_BeginPrint(object sender, PrintEventArgs e)
        {
            try
            {
                StrFormat = new StringFormat();
                StrFormat.Alignment = StringAlignment.Near;
                StrFormat.LineAlignment = StringAlignment.Center;
                StrFormat.Trimming = StringTrimming.EllipsisCharacter;
                StrFormatComboBox = new StringFormat();
                StrFormatComboBox.LineAlignment = StringAlignment.Center;
                StrFormatComboBox.FormatFlags = StringFormatFlags.NoWrap;
                StrFormatComboBox.Trimming = StringTrimming.EllipsisCharacter;

                ColumnLefts.Clear();
                ColumnWidths.Clear();
                ColumnTypes.Clear();
                CellHeight = 0;
                RowsPerPage = 0;

                CellButton = new Button();
                CellCheckBox = new CheckBox();
                CellComboBox = new ComboBox();

                TotalWidth = 0;

                foreach (DataGridViewColumn GridCol in dgv.Columns)
                {
                    if (!GridCol.Visible) continue;
                    if (!PrintDGV.SelectedColumns.Contains(GridCol.HeaderText)) continue;
                    TotalWidth += GridCol.Width;
                }

                PageNo = 1;
                NewPage = true;
                RowPos = 0;
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, "Erro", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        private static void DrawFooter(PrintPageEventArgs e, int RowsPerPage)
        {
            double cnt = 0;

            //Determina o numero de linhas a imprimir
            if (PrintAllRows)
            {
                if (dgv.Rows[dgv.Rows.Count - 1].IsNewRow)
                    cnt = dgv.Rows.Count - 2; // Quando o datagrid NAO permite add linhas
                else
                    cnt = dgv.Rows.Count - 1; // Quando o datagrid permite add linhas
            }
            else
            {
                cnt = dgv.SelectedRows.Count;
            }

            string PageNum = PageNo.ToString() + " de " +
                Math.Ceiling((double)(cnt / RowsPerPage)).ToString();

            e.Graphics.DrawString(PageNum, dgv.Font, Brushes.Black,
                e.MarginBounds.Left + (e.MarginBounds.Width -
                e.Graphics.MeasureString(PageNum, dgv.Font,
                e.MarginBounds.Width).Width) / 2, e.MarginBounds.Top +
                e.MarginBounds.Height + 31);
        }
    }
}
